<?php
/**
 * CreateUser:zlh
 * CreateTime:2022/1/15
 * Remark:该类为员工相关操作服务层
 */
namespace App\Service\Staff;

use App\common\cPermissionAuthCode;
use App\Consts\AuthConsts\AuthConsts;
use App\Consts\AuthConsts\MeAuthConsts;
use App\Consts\BaseConsts\BaseConsts;
use App\Consts\RedisConsts\RedisConsts;
use App\Consts\ResponseConsts\ResponseStatusConsts;
use App\Consts\Role\RoleConsts;
use App\Consts\TableConsts\TableConsts;
use App\Func\AuthFunc;
use App\Func\EncryptionFunc;
use App\Func\ResponseFunc;
use App\Func\RoleFunc;
use App\Func\ScopeFunc\AuthScopeStaffFunc;
use App\Func\TokenFuc;
use App\Models\Auth\AuthBasicModel;
use App\Models\Auth\AuthMenuModel;
use App\Models\Auth\AuthStaffModel;
use App\Models\Company\CompanyModel;
use App\Models\Department\DepartmentModel;
use App\Models\Position\PositionModel;
use App\Models\Staff\cStaffRole;
use App\Models\Staff\StaffDepartmentModel;
use App\Models\Staff\StaffModel;
use App\Scopes\MediationStaffScope;
use App\Tools\Token\LoginToken;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Redis;
use JetBrains\PhpStorm\ArrayShape;

class StaffService
{
    private StaffModel $_staffModel;
    private CompanyModel $_companyModel;
    private StaffDepartmentModel $_staffDepartmentModel;
    private DepartmentModel $_departmentModel;
    private PositionModel $_positionModel;
    private AuthStaffModel $_staffAuthModel;
    private AuthMenuModel $_authMenuModel;
    private AuthBasicModel $_authBasicModel;

    public function __construct()
    {
        $this->_authMenuModel = new AuthMenuModel();
        $this->_staffModel = new StaffModel();
        $this->_staffDepartmentModel = new StaffDepartmentModel();
        $this->_companyModel = new CompanyModel();
        $this->_departmentModel = new DepartmentModel();
        $this->_positionModel = new PositionModel();
        $this->_staffAuthModel = new AuthStaffModel();
        $this->_authBasicModel = new AuthBasicModel();
    }

    /**
     * 新增用户
     * @param $staffData
     * @return bool
     */
    public function addStaffService($staffData): bool
    {
        // 创建公私钥
        $rsaPuPvKey = EncryptionFunc::getRSAPuKeyPvKey();

        $staffDataModel = [
            $this->_staffModel->pu_key = $rsaPuPvKey['pu_key'],
            $this->_staffModel->pv_key = $rsaPuPvKey['pv_key'],
            $this->_staffModel->company_id =$staffData['company_id'],
            $this->_staffModel->staff_name = $staffData['staff_name'],
            $this->_staffModel->staff_sex = $staffData['staff_sex'] ?? BaseConsts::SEX_MAN,
            $this->_staffModel->staff_phone_number = $staffData['staff_phone_number'] ?? "",
            $this->_staffModel->staff_email = $staffData['staff_email'] ?? "",
            $this->_staffModel->staff_login_account = $staffData['staff_login_account'],
            $this->_staffModel->staff_login_password = EncryptionFunc::encryptionArgon2($staffData['staff_login_password']),
            $this->_staffModel->staff_status = BaseConsts::STATUS_STOP,
            $this->_staffModel->status = BaseConsts::STATUS_NORMAL,
            $this->_staffModel->is_open_ding_talk =>$staffData['is_open_ding_talk'] ? 1 : 2,
            $this->_staffModel->union_id = md5($staffData['company_id'].$staffData['staff_login_account']).time()
        ];
        $departments = $staffData['departments'];
        // 开启事务
        DB::beginTransaction();
        try {
            // 新增用户
            $staffId = $this->_staffModel->addStaffModel($staffDataModel);
            // 操作关联表
            // 操作部门表
            foreach($departments as $department){
                $this->_staffDepartmentModel->addStaffDepartment([
                    "staff_id" => $staffId,
                    "department_id" => $department['department_id'],
                    "position_id" => $department['position_id'],
                ]);
            }
            DB::commit();
        }catch (\Exception $error){
            DB::rollBack();
            throw new HttpResponseException( ResponseFunc::returnJson(
                'error',
                null,
                $error->getMessage(),
                ResponseStatusConsts::OK_200_RESPONSE_STATUS,
                
            ));

        }
        return true;
    }

    /**
     * 获取用户详情自定义字段
     * @param $staffId
     */
    public function getStaffDetailCustom($staffId,$select = ["*"])
    {
        // 获取用户详情
        return $this->_staffModel->getStaffDetail($staffId,$select);
    }

    /**
     * 获取用户详情
     * @param $staffId
     */
    public function getStaffDetail($staffId)
    {
        // 获取用户详情
        $staffInfo = $this->_staffModel->getStaffDetail($staffId,[
            'staff_id',
            'company_id',
            'company_id as company_name_str',
            'staff_name',
            'staff_sex',
            'staff_sex as staff_sex_str',
            'staff_phone_number',
            'staff_email',
            'staff_status',
            'staff_login_account',
            'staff.staff_status',
            'staff.staff_status as staff_status_name',
            'staff.staff_last_login_time as staff_last_login_time_name',
            'is_open_ding_talk',
            'staff_seats_pwd',
            'staff_seats_number',
        ]);
        if($staffInfo){
            // 获取用户部门情况
            if($this->_staffDepartmentModel->getStaffDepartments($staffId)){
                $staffInfo['departments'] = $this->_staffDepartmentModel->getStaffDepartments($staffId);
            }
        }
        return $staffInfo;
    }

    public function getMediatorList($filters,$pageSize)
    {
        // 获取当前权限下的所有用户
        $currentClientAuth = (new RoleFunc)->getStaffIdsByRoleCode(RoleConsts::ROLE_TYPE_TJY);
        $currentClientAuth = array_unique($currentClientAuth);
        $query = $this->_staffModel->select([
            'staff_id as key',
            'staff_id',
            'staff_name',
            'staff_phone_number',
            'staff_status'
        ])->whereIn('staff_id',$currentClientAuth)
        ->where('status',1)
        # 禁止全局 手动处理
        ->withoutGlobalScope(MediationStaffScope::class)
        ->whereIn('staff.staff_id',AuthScopeStaffFunc::getDepartmentStaffByCurrentStaffId())
        ->where('staff_status',1);
        if($filters){
            if(isset($filters['staff_id']) && $filters['staff_id']){
                $query = $query->where('staff.staff_id',$filters['staff_id']);
            }
            if(isset($filters['staff_name']) && $filters['staff_name']){
                $query = $query->where('staff.staff_name','LIKE',"%".$filters['staff_name']."%");
            }
        }
        return $this->_staffModel->getStaffList($query,$pageSize);

    }


    /**
     * 用户列表
     * @param $companyId
     * @param $filters
     * @param $pageSize
     * @return mixed
     */
    public function getStaffList($companyId,$filters,$pageSize): mixed
    {
        // 获取员工部门信息
        $query = $this->_staffModel->select([
            'staff.staff_id',
            'staff.staff_id as key',
            'staff.company_id',
            'staff.company_id as company_name_str',
            'staff.staff_name',
            'staff.staff_sex',
            'staff.staff_sex as staff_sex_str',
            'staff.staff_phone_number',
            'staff.staff_email',
            'staff.staff_login_account',
            'staff.staff_status',
            'staff.staff_status as staff_status_name',
            'staff.staff_last_login_time as staff_last_login_time_name',
        ])->where('staff.company_id',$companyId)
        ->where('staff.status',BaseConsts::STATUS_NORMAL);
        if($filters){
            if(isset($filters['company_id']) && $filters['company_id']){
                $query = $query->where('staff.company_id',$filters['company_id']);
            }

            if(isset($filters['staff_name']) && $filters['staff_name']){
                $query = $query->where('staff.staff_name','LIKE',"%".$filters['staff_name']."%");
            }

            if(isset($filters['staff_phone_number']) && $filters['staff_phone_number']){
                $query = $query->where('staff.staff_phone_number','LIKE',"%".$filters['staff_phone_number']."%");
            }

            if(isset($filters['staff_email']) && $filters['staff_email']){
                $query = $query->where('staff.staff_email','LIKE',"%".$filters['staff_email']."%");
            }

            if(isset($filters['staff_status']) && $filters['staff_status']){
                $query = $query->where('staff.staff_status',$filters['staff_status']);
            }

            if(isset($filters['staff_login_account']) && $filters['staff_login_account']){
                $query = $query->where('staff.staff_login_account','LIKE',"%".$filters['staff_login_account']."%");
            }

            if(isset($filters['department_id']) && $filters['department_id']){
                $query = $query->leftJoin(TableConsts::CY_STAFF_DEPARTMENT_TABLE_NAME.' as sd','sd.staff_id','staff.staff_id')
                ->where('sd.department_id',$filters['department_id']);
            }

            if(isset($filters['position_id']) && $filters['position_id']){
                $query = $query->leftJoin(TableConsts::CY_STAFF_DEPARTMENT_TABLE_NAME.' as sp','sp.staff_id','staff.staff_id')
                    ->where('sp.position_id',$filters['position_id']);
            }
        }
        return $this->_staffModel->getStaffList($query,$pageSize);

    }


    public function editStaffPwd($staffId,$staffData){
        // 校验原密码是否正确
        $staffInfo = $this->_staffModel->getStaffDetail($staffId,['staff_login_password']);
        if (!(Hash::check($staffData['old_password'],$staffInfo['staff_login_password']))) {
            throw new HttpResponseException( ResponseFunc::returnJson(
                'error',
                null,
                "原始密码错误",
                ResponseStatusConsts::OK_200_RESPONSE_STATUS,
            ));
        }
        // 校验两次密码是否一致
        if($staffData['new_password'] != $staffData['re_password']){
            throw new HttpResponseException( ResponseFunc::returnJson(
                'error',
                null,
                "两次密码输入不一致",
                ResponseStatusConsts::OK_200_RESPONSE_STATUS,
            ));
        }
        // 修改密码
        $res = $this->_staffModel->editStaffBasic($staffId,[
            'staff_login_password' => EncryptionFunc::encryptionArgon2($staffData['new_password'])
        ]);
        if($res){
            // 退出当前用户登录
            $lt = new LoginToken();
            $staffToken = $lt->setToken($staffId);
            $deptToken = $lt->setDeptToken($staffId);
            Redis::del($staffToken);
            Redis::del($deptToken);
        }


        return true;

    }

    /**
     * 修改用户基本信息
     * @param $staffId
     * @param $staffData
     * @return mixed
     */
    public function editStaffBasic($staffId,$staffData): mixed
    {
        $lt = new LoginToken();
        $deptToken = $lt->setDeptToken($staffId);
        $staffToken = $lt->setToken($staffId);
        // 删除不能修改的字段
        unset($staffData['staff_status']);
        unset($staffData['status']);
        unset($staffData['staff_login_account']);
        if(isset($staffData['staff_login_password']) && $staffData['staff_login_password']){
            $staffData['staff_login_password'] = EncryptionFunc::encryptionArgon2($staffData['staff_login_password']);
        }
        try {
            $res =  $this->_staffModel->editStaffBasic($staffId,$staffData);
        }catch (\Exception $exception){
            throw new HttpResponseException( ResponseFunc::returnJson(
                'error',
                null,
                "修改失败",
                ResponseStatusConsts::OK_200_RESPONSE_STATUS,
            ));
        }
        // 如果修改了密码则提出用户
        if(isset($staffData['staff_login_password'])){
            Redis::del($staffToken);
            Redis::del($deptToken);
        }
        return $res;
    }

    public function editCurrentStaffBasic($staffId,$staffData): mixed
    {
        $data = [];
        // 删除不能修改的字段
        if(isset($staffData['staff_name'])){
            $data['staff_name'] = $staffData['staff_name'];
        }
        if(isset($staffData['staff_phone_number'])){
            $data['staff_phone_number'] = $staffData['staff_phone_number'];
        }
        if(isset($staffData['staff_email'])){
            $data['staff_email'] = $staffData['staff_email'];
        }
        return $this->_staffModel->editStaffBasic($staffId,$data);
    }


    /**
     * 删除用户
     * @param $staffId
     * @return mixed
     */
    public function deleteStaff($staffId): mixed
    {
        return $this->_staffModel->editStaffBasic($staffId,[
           'status' => BaseConsts::STATUS_DELETE
        ]);
    }

    /**
     * 停用用户
     * @param $staffId
     * @return mixed
     */
    public function stopStaff($staffId): mixed
    {
        return $this->_staffModel->editStaffBasic($staffId,[
            'staff_status' => BaseConsts::STATUS_STOP
        ]);
    }



    /**
     * 启用用户
     * @param $staffId
     * @return mixed
     */
    public function startStaff($startStaffData): mixed
    {

        $staffId = $startStaffData['staffId'];
        // 判断用户启用必要条件
        // 当前用户未绑定角色
        $auth = AuthFunc::getstaffOwnAllRole($staffId);
        if(!$auth){
            throw new HttpResponseException( ResponseFunc::returnJson(
                'error',
                null,
                "当前用户未绑定角色不能激活",
                ResponseStatusConsts::OK_200_RESPONSE_STATUS,
            ));
        }

        return $this->_staffModel->editStaffBasic($staffId,[
            'staff_status' => BaseConsts::STATUS_START
        ]);
    }

    /**
     * 批量删除用户
     * @param $staffIds
     * @return mixed
     */
    public function bulkDeleteStaff($staffIds){
        return $this->_staffModel->editStaffIds($staffIds,[
            'status' => BaseConsts::STATUS_DELETE
        ]);
    }

    /**
     * 获取当前登录用户详细信息
     * @param $currentInfo
     * @return array
     */
    #[ArrayShape(['staff_detail' => "mixed", 'company_detail' => "mixed", 'department_detail' => "mixed", 'position_detail' => "mixed"])]
    public function getCurrentStaffByCurrentInfo($currentInfo): array
    {
        // 获取用户信息
       $staffDetail =  $this->_staffModel->getStaffDetail($currentInfo['staff_id'],[
            'staff_id',
            'staff_name',
            'staff_sex as staff_sex_str',
            'staff_phone_number',
            'staff_dingding_account',
            'staff_email',
            'staff_status',
            'staff_status as staff_status_name',
            'is_open_ding_talk',
            'staff_seats_pwd',
            'staff_seats_number',
            'staff_last_login_time as staff_last_login_time_name',
        ]);

        try {
            // 获取当前公司信息
            $companyDetail = $this->_companyModel->getCompanyInfoModelByCompanyId($currentInfo['company_id'],[
                'company_id',
                'company_name',
                'company_level as company_level_name'
            ]);

            // 获取当前部门职位基本信息
            $departmentDetail = $this->_departmentModel->getDepartmentInfoByDepartmentIdModel($currentInfo['department_id'],[
                'department_id',
                'department_name',
                'department_level as department_level_name',
            ]);

            $positionDetail = $this->_positionModel->getPositionInfoByPositionId($currentInfo['position_id'],[
                'position_id',
                'position_name',
                'position_remark'
            ]);
        }catch (\Exception $exception){
//            throw new HttpResponseException( ResponseFunc::returnJson(
//                'error',
//                null,
//                "登录超时,请重新登录",
//                ResponseStatusConsts::OK_200_RESPONSE_STATUS,
//            ));
        }

        return [
            'staff_detail' => $staffDetail ?? [] ,
            'company_detail' => $companyDetail ?? [],
            'department_detail' => $departmentDetail ?? [],
            'position_detail' => $positionDetail ?? [],
        ];

    }


    public function AuthorizeDetail($authData){
        $menus = $this->_staffDepartmentModel->getStaffDepartmentMenus(
            $authData['staff_id'],
            $authData['department_id']
        );
        $business = $this->_staffAuthModel->getStaffAuthByAuthType(
            $authData['staff_id'],
            $authData['department_id'],
            AuthConsts::OPERATION_AUTH_TYPE
        );
        $manage = $this->_staffAuthModel->getStaffAuthByAuthType(
            $authData['staff_id'],
            $authData['department_id'],
            AuthConsts::MANAGE_AUTH_TYPE
        );
        $newBusinessArr = [];
        if($business){
            $businessArr = $business->toArray();
            foreach($businessArr as $business){
                $newBusinessArr[$business['menu_id']] = [
                    'auth_id'=>$business['auth_id'],
                    'auth_key'=>$business['auth_key']
                ];
            }
        }

        $newManageArr = [];
        if($manage){
            $manageArr = $manage->toArray();
            foreach($manageArr as  $manage){
                $newManageArr[$manage['menu_id']] = [
                    'auth_id'=>$manage['auth_id'],
                    'auth_key'=>$manage['auth_key']
                ];
            }
        }

        // 获取
        $menus = $this->_authMenuModel->getAuthMenuMenu([
            'menu_id',
            'menu_name',
            'menu_url',
            'menu_parent_id',
        ]);
        foreach($menus as $key => $menu){
            $businessForm = [];
            $manageForm = [];
            $menus[$key]['select'] =false;
            if(isset($newBusinessArr[$menu['menu_id']])){
                $menus[$key]['select'] =true;
                $businessForm = [
                    $newBusinessArr[$menu['menu_id']]['auth_id']=>$newBusinessArr[$menu['menu_id']]['auth_key']
                ];
            }
            $menus[$key]['businessForm']= $businessForm ?? [];
            if(isset($newManageArr[$menu['menu_id']])){
                $menus[$key]['select'] =true;
                $manageForm = [
                    $newManageArr[$menu['menu_id']]['auth_id']=>$newManageArr[$menu['menu_id']]['auth_key']
                ];
            }
            $menus[$key]['manageForm'] = $manageForm ?? [];
            $menus[$key]['auth_list'] =
                [
                    'operation' => $this->_authBasicModel->getAuthSelectByMenuId($menu['menu_id'],
                        AuthConsts::OPERATION_AUTH_TYPE,
                        [
                            'auth_id',
                            'auth_name',
                            'auth_code',
                        ]),
                    'manage' =>  $this->_authBasicModel->getAuthSelectByMenuId($menu['menu_id'],
                        AuthConsts::MANAGE_AUTH_TYPE
                        ,
                        [
                            'auth_id',
                            'auth_name',
                            'auth_code',
                        ])
                ];
        }
        return $menus;
    }

    /**
     *
     * @param $authData
     */
    public function AuthorizeStaff($authData): bool
    {
        DB::beginTransaction();
        try {
            $staffId = $authData['staff_id'];
            $departmentId = $authData['department_id'];
            // 清空用户久权限
            $this->_staffDepartmentModel->editStaffDepartment([
                'staffId' =>$authData['staff_id'],
                'staffDepartmentId' =>$authData['department_id'],
            ],[
                'menus' => ''
            ]);
            $this->_staffAuthModel->deleteAuthByStaffId($staffId);
            // 新增计算用户能够访问的菜单权限
            $menuIds = implode(',',array_column($authData['auths'],'menu_id'));
            // 修改用户菜单字段
            $this->_staffDepartmentModel->editStaffDepartment([
                'staffId' =>$authData['staff_id'],
                'staffDepartmentId' =>$authData['department_id'],
            ],[
                'menus' => $menuIds
            ]);
            // 生成权限关联表
            foreach($authData['auths'] as $value){
                $data = [
                    'staff_id'=>$staffId,
                    'auth_id'=>$value['auth_id'],
                    'department_id' => $departmentId,
                    'auth_key'=>$value['auth_key'],
                ];
                $this->_staffAuthModel->saveAllAuth($data);
            }
            DB::commit();
        }catch (\Exception $error){
            DB::rollBack();
            throw new HttpResponseException( ResponseFunc::returnJson(
                'error',
                null,
                $error->getMessage(),
                ResponseStatusConsts::OK_200_RESPONSE_STATUS,

            ));

        }
        return true;
    }

    public function bindDingTalk($dingTalkUserId,$unionId,$staffId)
    {
       return $this->_staffModel->editStaffBasic($staffId,[
            'is_logged' => 1,
            'staff_dingding_account' => $dingTalkUserId,
            'staff_dingding_account_unionid' => $unionId
        ]);
    }

    public function getDingTalkIdIsCompanyBind(mixed $dingTalkUserId,$companyId)
    {
        return $this->_staffModel->getDingTalkIdIsCompanyBind($dingTalkUserId,$companyId)['staff_id'] ?? false;
    }

    public function getStaffDetailByDingTalkId(mixed $dingTalkUserId)
    {
        return $this->_staffModel->getStaffDetailByDingTalkId($dingTalkUserId);
    }




}